<?php

namespace core;

class kyo
{
    static $config = null;

    public function __construct()
    {
        include __DIR__.DS."constants.php";
        self::$config = include __DIR__.DS."configs.php";
        include __DIR__.DS."functions.php";

        set_exception_handler(__NAMESPACE__.'\kyo::kyoException');
        set_error_handler(__NAMESPACE__.'\kyo::kyoError');
        spl_autoload_register(__NAMESPACE__."\kyo::autoload");

        $template_engine = C('TEMPLATE_ENGINE');
        if ($template_engine !== null)
            C('AUTOLOAD_DIR', VENDOR_PATH.strtolower($template_engine).DS, true);
    }

    static public function route()
    {
        $url = trim($_SERVER['PATH_INFO'] ?? $_GET['s'] ?? null, '/');
        $url = strlen($url) == 0 ? [] : explode('/', $url);

        $mod = C('DEFAULT_MODULE') !== null ? strtolower(array_shift($url) ?? C('DEFAULT_MODULE')) : null;

        $controller = ucfirst(strtolower(array_shift($url) ?? C('DEFAULT_CONTROLLER')));
        $method = strtolower(array_shift($url) ?? C('DEFAULT_METHOD'));

        $arg = $url;
        /*
         * $len = count($url);
         * $arg = [];
         * if ($len >= 2) {
         *     $len -= 1;
         *     for ($i = 0; $i < $len; $i += 2) {
         *         $arg[$url[$i]] = $url[$i + 1];
         *     }
         * }
         */
        return compact("mod", "controller", "method", "arg");
    }

    static public function appLoad()
    {
        $path = APP_COMMON_PATH.'constants.php';
        file_exists($path) and include $path;

        $path = APP_COMMON_PATH.'configs.php';
        if (file_exists($path)) {
            $config = include $path;
            self::$config = $config + self::$config;
        }

        $path = APP_COMMON_PATH.'functions.php';
        file_exists($path) and include $path;
    }

    public function run()
    {
        $route = self::route();
        // print_r($route);
        C('CONTROLLER_NAME', $route['controller']);
        C('ACTION_NAME', $route['method']);
        C('ACTION_ARG', serialize($route['arg']));

        $classname = '\\';
        if ($route['mod'] !== null) {
            C('MODULE_NAME', $route['mod']);
            $classname .= $route['mod'].'\\';
        }
        $classname .= $route['controller'];

        self::appLoad();

        $obj = new $classname();
        call_user_func_array(array($obj, $route['method']), $route['arg']);
    }

    public function autoload($class)
    {
        // echo "class: ", $class, "<br />";
        $classfile = str_replace('\\', DS, $class).".class.php";

        foreach (C('AUTOLOAD_DIR') as $dir) {
            $path = $dir.$classfile;
            // echo $path."<br />";
            if (file_exists($path)) {
                include $path;
                break;
            }
        }
    }

    static public function halt($str = null)
    {
        global $s;
        echo ((microtime(true) - $s));
        exit($str);
    }

    static public function kyoError($no, $str, $file, $line)
    {
        if (!DEBUG)
            kyo::halt(0);

        echo '<h1>Kyo Error:</h1>';
        echo '<h3>&emsp;&emsp;发生错误文件名+行号: <br />';
        echo '&emsp;&emsp;&emsp;&emsp;', $file, ' +'.$line.'</h3>';
        echo '<h3>&emsp;&emsp;发生错误(代码): 信息: <br />';
        echo '&emsp;&emsp;&emsp;&emsp;(', $no, '): '.$str.'</h3>';
        kyo::halt(0);
    }

    static public function kyoException($e)
    {
        echo '<h1>kyo Exception: ', $e->getMessage(), '</h1>';
        kyo::halt(0);
    }
}
